use std::str::FromStr;
use sea_orm::{
    ActiveModelTrait, ColumnTrait, EntityTrait, PaginatorTrait, QueryFilter, QueryOrder,
};
use sea_orm::ActiveValue::Set;
use common::ctx::get_db_by_key;
use common::error::MyError;
use common::page::{BasePage, PageResult};
use entity::accounts;
use entity::prelude::Accounts;
use model::accounts::{AccountsPage, CreateAccounts, ResetPasswordModel};


use crate::manager::base::BaseManager;

pub struct AccountsManager {}

impl BaseManager<i32,accounts::Model,AccountsPage,CreateAccounts,accounts::Model> for AccountsManager {
    async fn list() -> Result<Vec<accounts::Model>, MyError> {
        let list = Accounts::find().all(&*get_db_by_key("d_taiwan")?).await?;
        Ok(list)
    }

    async fn page(page: AccountsPage) -> Result<PageResult<accounts::Model>, MyError> {
        let mut find = Accounts::find();
        //排序
        if let Some(sorter) = page.get_order() {
            let field = accounts::Column::from_str(sorter.field.as_str()).or_else(|e| {
                Err(MyError::DBError(format!(
                    "获取排序字段失败：{}",
                    e.to_string()
                )))
            })?;
            find = find.order_by(field, sorter.order());
        }

        if let Some(ref account_name) = page.accountname {
            find = find.filter(accounts::Column::Accountname.like(format!("%{}%", account_name)));
        }
        if let Some(uid) = page.uid {
            find = find.filter(accounts::Column::Uid.eq(uid));
        }

        //校验并获取分页数据
        let page_data = page.check_page_data();
        //每页大小
        let db_conn = &*get_db_by_key("d_taiwan")?;
        let paginator = find.paginate(db_conn, page_data.page_size);

        //执行分页查询
        let record = paginator.fetch_page(page_data.page - 1).await?;
        //总条数
        let total = paginator.num_items().await?;
        //返回分页结果
        Ok(PageResult {
            page: page_data.page,
            page_size: page_data.page_size,
            total,
            record,
        })
    }

    async fn info(id: i32) -> Result<Option<accounts::Model>, MyError> {
        let res = Accounts::find_by_id(id).one(&*get_db_by_key("d_taiwan")?).await?;
        Ok(res)
    }

    async fn add(form: CreateAccounts) -> Result<i32, MyError> {
        let account_name = form
            .accountname
            .ok_or(MyError::ServerError("账号不能为空".to_string()))?;
        let password = form
            .password
            .ok_or(MyError::ServerError("密码不能为空".to_string()))?;
        let password = format!("{:x}", md5::compute(password));
        let model = accounts::ActiveModel {
            uid: Default::default(),
            accountname: Set(Some(account_name)),
            password: Set(Some(password)),
            qq: Default::default(),
            dzuid: Default::default(),
        }
            .insert(&*get_db_by_key("d_taiwan")?)
            .await?;
        Ok(model.uid)
    }

    async fn update(form: accounts::Model) -> Result<i32, MyError> {
        let entity = Accounts::find_by_id(form.uid)
            .one(&*get_db_by_key("d_taiwan")?)
            .await?
            .ok_or(MyError::ServerError(format!(
                "accounts [{:?}] does not exist",
                form.uid
            )))?;
        let mut entity: accounts::ActiveModel = entity.into();
        if form.accountname.is_some() {
            entity.accountname = Set(form.accountname);
        }
        let result = entity.update(&*get_db_by_key("d_taiwan")?).await?;
        Ok(result.uid)
    }

    async fn delete(id: i32) -> Result<bool, MyError> {
        let res = Accounts::delete_by_id(id).exec(&*get_db_by_key("d_taiwan")?).await?;
        Ok(res.rows_affected == 1)
    }
}

impl AccountsManager {
    pub async fn reset_password(form: ResetPasswordModel) -> Result<bool, MyError> {
        let entity = Accounts::find_by_id(form.uid)
            .one(&*get_db_by_key("d_taiwan")?)
            .await?
            .ok_or(MyError::ServerError(format!(
                "accounts [{:?}] does not exist",
                form.uid
            )))?;
        let mut entity: accounts::ActiveModel = entity.into();
        entity.password = Set(Some(format!("{:?}",md5::compute(form.password))));
        let _result = entity.update(&*get_db_by_key("d_taiwan")?).await?;
        Ok(true)
    }

    pub async fn get_by_username(username: String) -> Result<Option<accounts::Model>, MyError> {
        let mut find = Accounts::find();
        find = find.filter(accounts::Column::Accountname.eq(username));
        let res = find.one(&*get_db_by_key("d_taiwan")?)
            .await?;
        Ok(res)
    }
}